package user_service

import (
	"errors"
	"starry_sky/internal/core"
	"starry_sky/internal/dal"
	"starry_sky/internal/dal/permission-dal"
	"starry_sky/internal/dal/role-dal"
	"starry_sky/internal/dal/user-dal"
	user_dto "starry_sky/internal/dto/user-dto"
	"starry_sky/internal/model"
	"starry_sky/internal/tools/encryption"
	"starry_sky/internal/tools/logger"
)

func FindUserByUserName(UserName string) (model.User, error) {
	user, err := user_dal.FindUserByUserName(UserName)
	if logger.HasError(err) {
		return model.User{}, errors.New("查询用户失败")
	}
	return user, nil
}

func CreateUser(user *model.User) error {
	var hasUsername int64
	err := dal.JudgmentRepetition[model.User](&hasUsername, map[string]any{"username": user.Username}, user.ID)
	user.Password = encryption.MD5(user.Password)
	if logger.HasError(err) {
		return errors.New("查询用户是否重复失败")
	}
	if hasUsername > 0 {
		return errors.New("用户名已存在")
	}
	user.Status = true
	err = dal.Insert(user)
	if logger.HasError(err) {
		return errors.New("新增用户失败")
	}
	return nil
}

func UpdateUser(user *model.User) error {
	var oldUser model.User
	oldUser.ID = user.ID
	err := dal.FindById(&oldUser)
	if logger.HasError(err) {
		return errors.New("查询用户失败")
	}
	var hasUsername int64
	err = dal.JudgmentRepetition[model.User](&hasUsername, map[string]any{"username": user.Username}, user.ID)
	if logger.HasError(err) {
		return errors.New("查询用户是否重复失败")
	}
	if hasUsername > 0 {
		return errors.New("用户名已存在")
	}
	oldUser.Username = user.Username
	oldUser.Nickname = user.Nickname
	oldUser.Remark = user.Remark
	oldUser.Email = user.Email
	oldUser.Mobile = user.Mobile
	oldUser.Sex = user.Sex
	oldUser.Avatar = user.Avatar
	oldUser.Updater = user.Updater
	err = dal.Save(&oldUser)
	if logger.HasError(err) {
		return errors.New("更新用户失败")
	}
	return nil
}

func GetUserInfoById(id string) (map[string]any, error) {
	if id == "" {
		return nil, errors.New("用户id不能为空")
	}
	var user model.User
	user.ID = id
	err := dal.FindById(&user)
	if logger.HasError(err) {
		return nil, errors.New("查询用户失败")
	}
	if user.ID == "" {
		return nil, errors.New("用户不存在")
	}
	var roleStrs []string
	var roles []*model.Role
	err = role_dal.ListRolesByUser(&user, &roles)
	if logger.HasError(err) {
		return nil, errors.New("查询用户角色失败")
	}
	// 判断是否是管理员
	isAdmin := false
	for _, role := range roles {
		if role.Code == core.AdminRoleCode {
			isAdmin = true
			break
		}
	}
	var permissionStrs []string
	// 存储无重复的permission
	var allPermissions []*model.Permission
	if isAdmin {
		roleStrs = append(roleStrs, core.AdminRoleCode)
		err := dal.GetAll(&allPermissions)
		if logger.HasError(err) {
			return nil, errors.New("查询管理员权限失败")
		}
	} else {
		// 存放当前已存在的permission的id
		permissionIdSet := core.NewSet()
		for _, role := range roles {
			roleStrs = append(roleStrs, role.Code)
			var permissions []*model.Permission
			err := permission_dal.ListPermissionByRole(role, &permissions)
			if logger.HasError(err) {
				return nil, errors.New("查询用户权限失败")
			}
			for _, permission := range permissions {
				if permissionIdSet.Has(permission.ID) {
					continue
				}
				permissionIdSet.Add(permission.ID)
				allPermissions = append(allPermissions, permission)
			}
		}
	}
	var menus []*model.Permission
	var MenuMap = make(map[string][]*model.Permission)
	for _, permission := range allPermissions {
		// 存储全部可用按钮的code
		if permission.Type == core.Button {
			permissionStrs = append(permissionStrs, permission.Permission)
		}
		//整理菜单数据
		if permission.Type != core.Button {
			if permission.ParentId == "" {
				menus = append(menus, permission)
			} else {
				if _, ok := MenuMap[permission.ParentId]; !ok {
					MenuMap[permission.ParentId] = make([]*model.Permission, 0)
				}
				MenuMap[permission.ParentId] = append(MenuMap[permission.ParentId], permission)
			}
		}
	}
	tree := assembleMenuTree(menus, MenuMap)
	return map[string]any{
		"user":        user,
		"roles":       roleStrs,
		"permissions": permissionStrs,
		"tree":        tree,
	}, nil
}

// GetMenuTree 获取菜单树
func assembleMenuTree(menus []*model.Permission, menuMap map[string][]*model.Permission) []*model.Permission {
	for _, menu := range menus {
		if children, ok := menuMap[menu.ID]; ok {
			menu.Children = assembleMenuTree(children, menuMap)
		}
	}
	return menus
}

// BindUserAndRole 绑定用户角色
func BindUserAndRole(bindUserAndRole user_dto.BindUserAndRole) error {
	var user model.User
	user.ID = bindUserAndRole.UserId
	err := dal.FindById(&user)
	if logger.HasError(err) {
		return errors.New("查询用户失败")
	}
	var roles []model.Role
	for _, roleId := range bindUserAndRole.RoleIds {
		var role model.Role
		role.ID = roleId
		err := dal.FindById(&role)
		if logger.HasError(err) {
			return errors.New("查询角色失败")
		}
		roles = append(roles, role)
	}
	tx := dal.TransactionBegin()
	err = user_dal.ClearUserAndRole(tx, &user)
	if logger.HasError(err) {
		err := dal.TransactionRollback(tx)
		if logger.HasError(err) {
			logger.SysErrorF("事务回滚失败")
		}
		return errors.New("清除用户角色失败")
	}
	err = user_dal.BindUserAndRole(tx, &user, roles)
	if logger.HasError(err) {
		err := dal.TransactionRollback(tx)
		if logger.HasError(err) {
			logger.SysErrorF("事务回滚失败")
		}
		return errors.New("绑定用户角色失败")
	}
	err = dal.TransactionCommit(tx)
	if logger.HasError(err) {
		return errors.New("事务提交失败")
	}
	return nil
}
